package com.mrx.xfriendship.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mrx.commons.annotations.XLog;
import com.mrx.commons.util.asserts.Asserts;
import com.mrx.xfriendship.converter.PostConverter;
import com.mrx.xfriendship.dao.PostMapper;
import com.mrx.xfriendship.model.dto.PageDTO;
import com.mrx.xfriendship.model.dto.PostDTO;
import com.mrx.xfriendship.model.po.PostPO;
import com.mrx.xfriendship.model.po.UserDetailPO;
import com.mrx.xfriendship.model.po.UserPO;
import com.mrx.xfriendship.model.vo.ListPostPageVO;
import com.mrx.xfriendship.model.vo.PageVO;
import com.mrx.xfriendship.model.vo.PostManagePageVO;
import com.mrx.xfriendship.model.vo.PostVO;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Mr.X
 * @since 2023-01-14 10:06
 */
@XLog
@Service
@DubboService
public class PostServiceImpl implements IPostService {

    @Resource
    private PostMapper postMapper;

    @Resource
    private PostConverter postConverter;

    @Resource
    private IRedisService redisService;

    @Resource
    private IPSearcherService ipSearcherService;

    private static final Logger logger = LoggerFactory.getLogger(PostServiceImpl.class);

    @Override
    public PageDTO<PostDTO> listPosts(String ip, @NonNull ListPostPageVO pageVO) {
        try (Page<?> page = PageHelper.startPage(pageVO.getPage(), pageVO.getSize())) {
            redisService.plusSitePV(ipSearcherService.search(ip));
            List<PostPO> pagePost = postMapper.selectPage(pageVO);
            // 处理不存在的用户的帖子
            pagePost.forEach(this::handleDefaultUserPO);
            return PageDTO.newPage(pageVO, postConverter.toDTO(pagePost)
                    .stream()
                    .peek(it -> {
                        it.setContent(null);
                        it.setComment(Collections.emptyList());
                    }).collect(Collectors.toList()), page.getTotal());
        }
    }

    @Override
    public PageDTO<PostDTO> listPostsByUserId(@NonNull Integer userId) {
        // 暂时先这么做
        PageVO pageVO = new PageVO();
        try (Page<Object> page = PageHelper.startPage(pageVO.getPage(), pageVO.getSize())) {
            return PageDTO.newPage(pageVO, postConverter.toDTO(postMapper.selectByUserId(userId)), page.getTotal());
        }
    }

    @NonNull
    @Override
    @Transactional
    public PostDTO postDetail(Integer id) {
        PostPO po = Asserts.POST_NOT_EXISTS.checkNotNull(postMapper.selectByPrimaryKey(id));
        logger.debug("postDetail: {}", po);
        // postMapper.addViewCount(id);
        redisService.plusPostPV(id);
        // 处理不存在的用户的帖子
        handleDefaultUserPO(po);
        PostDTO dto = postConverter.toDTO(po);
        // 先将 redis 里的数据展示给用户
        dto.setViewCount(dto.getViewCount() + redisService.getPostPV(id));
        return dto;
    }

    @Override
    public void publish(PostVO vo) {
        postMapper.insertSelective(postConverter.toPO(vo));
    }

    @Override
    @Transactional
    public void syncPV(@NonNull JSONObject json) {
        json.forEach((k, v) -> postMapper.updatePVWithIncrement(k, Integer.parseInt(v + "")));
    }

    @Override
    public PageDTO<PostDTO> listPosts(PostManagePageVO vo) {
        try (Page<?> page = PageHelper.startPage(vo.getPage(), vo.getSize())) {
            List<PostPO> list = postMapper.selectPageCondition(vo);
            // 处理用户被删除的情况
            list.forEach(this::handleDefaultUserPO);
            return PageDTO.newPage(vo, postConverter.toDTO(list), page.getTotal());
        }
    }

    @Override
    public void updatePost(PostDTO dto) {
        postMapper.updateByPrimaryKeySelective(postConverter.toPO(dto));
    }

    @Override
    public void delete(Integer id) {
        postMapper.deleteByPrimaryKey(id);
    }

    private void handleDefaultUserPO(PostPO po) {
        if (po.getAuthor() == null) po.setAuthor(defaultUserPO());
    }

    private UserPO defaultUserPO() {
        UserPO author = new UserPO();
        author.setName("账号已删除");
        UserDetailPO userDetail = new UserDetailPO();
        userDetail.setAvatar("20230121/69c09d7b121aa6dc9fbc4b2bbe76bc4b.jpg");
        author.setUserDetail(userDetail);
        return author;
    }

}
